from typing import Tuple, Dict, Any, Optional, Union, Generator
from fastapi import Path
from openai import OpenAI
import json
import pandas as pd
from pandasql import sqldf
import re
from app.ai.ai_prompt import AiPrompt
from app.ai.ai_prompttask import AiPromptTask
from loguru import logger  # 导入 logger
from app.datatk.data_help import DataHelp
from config import AI_FXMODEL 
from uuid import uuid4
import time
from app.models.db import ModelCallLog
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from datetime import datetime
from app.models.db import DATABASETB_URL


class AIGetData:
    def __init__(self, base_url, api_key, session_id=None):
        self.base_url = base_url
        self.api_key = api_key
        self.datamodel = AI_FXMODEL  # 使用配置项中的 datamodel 值
        self.timeout = 120  # 设置超时时间为120秒
        self.session = None  # 用于记录日志的数据库会话
        self.session_id = session_id  # 添加session_id属性，用于日志关联
     # 新增函数: 读取Excel文件
     
    def _estimate_tokens(self, text: str) -> int:
        """
        预估文本的token数量
        使用简单的启发式算法：英文约4字符=1token，中文约1.5字符=1token
        """
        if not text:
            return 0
            
        # 统计中文字符和其他字符
        chinese_chars = len([c for c in text if '\u4e00' <= c <= '\u9fff'])
        other_chars = len(text) - chinese_chars
        
        # 预估token数量：中文字符按1.5字符=1token，其他字符按4字符=1token
        estimated_tokens = int(chinese_chars / 1.5 + other_chars / 4)
        
        # 添加一些系统token的开销（消息格式化等）
        system_overhead = 10
        
        return estimated_tokens + system_overhead
    
    def _chat_completion(
        self, 
        model: str, 
        prompt: str, 
        stream: bool = False, 
        role: str = "user", 
        prompt_type: str = "general",  # 提示词类型，用于日志分类
        **kwargs
    ) -> Union[Dict[str, Any], Generator]:
        """调用OpenAI聊天完成接口的通用方法，支持日志记录"""
        
        # 预估提示词长度和token数量
        estimated_tokens = self._estimate_tokens(prompt)
     
        
        client = OpenAI(api_key=self.api_key, base_url=self.base_url)
        
        # 构建基本参数
        params = {
            "model": model,
            "messages": [{"role": role, "content": prompt}],
            "stream": stream,
            **kwargs
        }
        
        # 创建数据库会话
        engine = create_engine(DATABASETB_URL)
        Session = sessionmaker(bind=engine)
        session = Session()
        
        # 创建日志记录
        log_record = ModelCallLog(
            id=str(uuid4()),
            model_name=model,
            prompt_type=prompt_type,
            prompt_content=prompt,
            created_at=datetime.now(),
            user_id="test",
            tokens_prompt=estimated_tokens
        )
        # 记录调用开始时间
        start_time = time.time()
        
        # 调用API并记录日志
        try:
            # 调用API
            response = client.chat.completions.create(**params)
            
            # 计算调用耗时
            duration_ms = int((time.time() - start_time) * 1000)
            
            # 更新日志记录的耗时
            log_record.duration_ms = duration_ms
            log_record.status_code = 200  # 假设成功
            
            # 如果是流式响应，需要特殊处理
            if stream:
                # 创建一个生成器包装器来处理流式响应的日志记录
                def log_stream_response():
                    # 累积完整的响应内容
                    full_response = ""
                    
                    for chunk in response:
                        content = chunk.choices[0].delta.content
                        if content:
                            full_response += content
                            yield chunk
                    
                    # 流式响应完成后，更新日志记录
                    log_record.response_content = full_response
                    
                    # 尝试获取token信息（OpenAI可能不会为流式响应提供）
                    if hasattr(response, 'usage') and response.usage:
                        # 直接使用属性访问，而不是get方法
                        log_record.tokens_prompt = getattr(response.usage, 'prompt_tokens', 0)
                        log_record.tokens_completion = getattr(response.usage, 'completion_tokens', 0)
                        log_record.tokens_total = getattr(response.usage, 'total_tokens', 0)
                    
                    # 保存日志
                    try:
                        session.add(log_record)
                        session.commit()
                    except Exception as e:
                        session.rollback()
                    finally:
                        session.close()
                
                return log_stream_response()
            else:
                # 非流式响应，直接记录完整的响应内容
                log_record.response_content = response.choices[0].message.content
                
                # 获取token使用情况
                if hasattr(response, 'usage') and response.usage:
                    # 直接使用属性访问，而不是get方法
                    log_record.tokens_prompt = getattr(response.usage, 'prompt_tokens', 0)
                    log_record.tokens_completion = getattr(response.usage, 'completion_tokens', 0)
                    log_record.tokens_total = getattr(response.usage, 'total_tokens', 0)
                
                # 保存日志
                try:
                    session.add(log_record)
                    session.commit()
                except Exception as e:
                    session.rollback()
                finally:
                    session.close()
                
                return response
        except Exception as e:
            # 记录错误信息
            duration_ms = int((time.time() - start_time) * 1000)
            log_record.duration_ms = duration_ms
            log_record.status_code = 500  # 错误状态码
            log_record.error_message = str(e)
            
            # 保存错误日志
            try:
                session.add(log_record)
                session.commit()
                logger.error(f"模型调用失败: {model}, 类型: {prompt_type}, 错误: {str(e)}")
            except Exception as log_err:
                session.rollback()
                logger.error(f"保存模型调用错误日志失败: {str(log_err)}")
            finally:
                session.close()
                
            # 重新抛出原始异常
            raise

    def _parse_response(self, response: dict) -> list:
        """解析大模型响应，支持两种格式：带```json```标记和纯JSON格式"""
        try:
            content = response.choices[0].message.content
            
            # 智能检测JSON格式
            json_str = ""
            if '```json' in content:
                # 旧格式：带```json```标记
                try:
                    json_str = content.split('```json\n')[1].split('\n```')[0]
                except IndexError:
                    # 如果分割失败，尝试其他分割方式
                    try:
                        json_str = content.split('```json')[1].split('```')[0]
                    except IndexError:
                        # 最后尝试直接使用内容
                        json_str = content
            else:
                # 新格式：纯JSON格式，直接使用整个内容
                json_str = content
            
            # 处理转义字符和换行符
            json_str = json_str.strip()  # 移除首尾空白字符
            
            # 对于纯JSON格式，保持原有的换行结构以便解析
            # 只有当检测到压缩格式时才移除换行符
            content_lines = json_str.split('\n')
            if len(content_lines) == 1:  # 单行压缩格式
                json_str = json_str.replace('\\n', '')  # 移除转义的换行符
            
            # 修复缺少双引号的JSON属性名问题
            # 匹配形如 task_name": 的模式并修复为 "task_name":
            json_str = re.sub(r'(\s+)([a-zA-Z_][a-zA-Z0-9_]*)("\s*:)', r'\1"\2\3', json_str)
            
            # 在尝试解析JSON之前，先处理SQL语句中包含双引号的情况
            # 匹配所有"SQL"字段中的内容并进行处理
            def replace_sql_quotes(match):
                sql = match.group(1)
                # 将SQL中的双引号替换为单引号
                processed_sql = sql.replace('"', '\\"')
                return f'"SQL":"{processed_sql}"'
            
            json_str = re.sub(r'"SQL":"(.*?)"', replace_sql_quotes, json_str)
            
            # 处理 JavaScript 函数
            # 将形如 function(params) { return ... } 的函数转换为字符串
            json_str = re.sub(
                r'function\s*\((.*?)\)\s*{(.*?)}',
                lambda m: f'"function({m.group(1)}) {{{m.group(2)}}}"',
                json_str
            )
            
            # 处理 formatter 中的函数
            json_str = re.sub(
                r'"formatter":\s*function\s*\((.*?)\)\s*{(.*?)}',
                lambda m: f'"formatter": "function({m.group(1)}) {{{m.group(2)}}}"',
                json_str
            )
            
            # 记录处理后的 JSON 字符串，方便调试
            logger.debug(f"解析模式: {'带标记格式' if '```json' in content else '纯JSON格式'}")
            logger.debug(f"处理后的JSON字符串: {json_str[:200]}...")  # 只显示前200字符
            
            # 尝试解析JSON
            result = json.loads(json_str)
            
            # 确保返回的是列表格式
            if isinstance(result, dict):
                return [result]
            elif isinstance(result, list):
                return result
            else:
                logger.warning(f"JSON解析结果不是预期格式: {type(result)}")
                return []
                
        except (KeyError, IndexError, json.JSONDecodeError) as e:
            logger.error(f"响应解析失败: {str(e)}")
            logger.error(f"原始内容: {content[:500] if 'content' in locals() else '未获取'}...")
            logger.error(f"处理后JSON: {json_str[:500] if 'json_str' in locals() else '未生成'}...")
            return []
        except Exception as e:
            logger.error(f"解析过程中发生未知错误: {str(e)}")
            return []

    def generate_response(self, message):
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=message,
            prompt_type='chat_response'
        )
        return self._parse_response(completion)
        
    def generate_analysis_plan(self, table_structure: str, existing_dimensions=None):
        """
        基于大模型生成分析建议
        
        参数:
            table_name (str): 表名
            table_structure (str): 表结构信息的JSON字符串
            existing_dimensions (list, optional): 已有的分析维度列表，默认为None
            
        :return: 结构化分析建议列表
        """
        print("分析方向开始")
        prompt = AiPrompt.build_dimension_analysis_prompt(table_structure, existing_dimensions)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='analysis_plan'
        )
        
        return self._parse_response(completion)
        
    def generate_sql_plan(self, table_info: str, query: str, hismsg: str) -> Tuple[str]:
        """
        基于大模型生成数据查询SQL
        """
        prompt = AiPrompt.build_user_intent_prompt(table_info, query, hismsg)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='user_intent_sql'
        )
        
        return self._parse_response(completion)

    def generate_direction_report(self, message: str, jsondata):
        """
         基本分析方向生成分析报告
        """
        prompt = AiPrompt.build_smart_response_prompt(message, jsondata)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='smart_direction_report'
        )
        
        return completion.choices[0].message.content

    def generate_hfmsg(self,  message: str, all_task_data):
        """
        基于数据生成回复消息
        """
        # 使用新的智能提示词方法，自动判断用户意图
        prompt = AiPrompt.build_smart_response_prompt(message, all_task_data)
        prompt_type = "smart_response"
            
        # 使用公共方法_chat_completion替代原始代码，流式输出
        # 流式输出的日志记录已在_chat_completion方法中处理
        response_generator = self._chat_completion(
            model=self.datamodel,
            prompt=prompt,
            stream=True,
            role="system",
            temperature=0,
            top_p=0,
            prompt_type=prompt_type
        )
        
        # 直接返回流式响应（此时已包含日志记录逻辑）
        for chunk in response_generator:
            content = chunk.choices[0].delta.content
            if content:
                yield content
            
    def generate_echarts_config(self, sql: str, chart_type: str, user_request: str, datajson:str):
        """
        根据SQL语句、表信息、图表类型和用户需求生成Echarts配置项
        
        参数:
            sql (str): 统计SQL语句，可能包含多维度统计
            tablename (str): 表名
            columns (list): 表的列名列表
            chart_type (str): 推荐图表类型，如"饼图"、"柱状图"等
            user_request (str): 用户输入的相关要求
            
        返回:
            dict: Echarts的完整配置项JSON对象
        """
        # 构建提示词
        prompt = AiPrompt.build_echarts_config_prompt(sql, chart_type, user_request, datajson)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='echarts_config'
        )
        
        return self._parse_response(completion)

    def generate_g2_config(self, sql: str, chart_type: str, user_request: str, datajson: str = None):
        """
        根据SQL语句、数据摘要、样本数据和用户需求生成G2图表配置项
        
        参数:
            sql (str): 统计SQL语句，可能包含多维度统计
            chart_type (str): 推荐图表类型，如"饼图"、"柱状图"等
            user_request (str): 用户输入的相关要求
            datajson (str, optional): 查询结果数据的JSON字符串
            
        返回:
            dict: G2的完整配置项JSON对象
        """
        # 构建提示词
        prompt = AiPrompt.build_g2_config_prompt(sql, chart_type, user_request, datajson)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='g2_config'
        )
        
        return self._parse_response(completion)

    def generate_report(self, report_type: str, report_data: str, report_title: str):
        """
        根据报告类型生成数据报告，支持流式输出
        
        参数:
            report_type (str): 报告类型 cleaning:清洗报告 summary:摘要报告
            report_data (str): 报告数据，可能是JSON字符串格式的清洗日志或数据摘要
            report_title (str): 报告标题
            
        返回:
            generator: 流式输出的报告内容
        """
        from app.ai.ai_prompt import AiPrompt
        
        # 根据报告类型选择不同的提示词
        if report_type == "cleaning":  # 清洗报告
            prompt = AiPrompt.build_data_cleaning_report_prompt(report_data)
        elif report_type == "summary":  # 摘要报告
            prompt = AiPrompt.build_data_summary_report_prompt(report_data)
        else:
            # 如果报告类型不支持，返回错误信息
            yield f"不支持的报告类型: {report_type}"
            return
        
        # 开始流式生成
        logger.info(f"开始生成{report_title}，报告类型：{report_type}")
        model_to_use = AI_FXMODEL
        
        # 使用公共方法_chat_completion，流式输出（包含日志记录功能）
        for chunk in self._chat_completion(
            model=model_to_use,
            prompt=prompt,
            stream=True,
            temperature=0.7,
            max_tokens=2000,
            prompt_type=f'{report_type}_report'
        ):
            content = chunk.choices[0].delta.content
            if content:
                yield content

    def generate_and_save_analysis_outline(self, data_summary: str, title: str, dataset_context: str = ""):
        """
        生成分析大纲并返回结构化JSON数据
        
        参数:
            data_summary (str): 数据摘要JSON字符串，用于生成分析大纲
            title (str): 分析大纲标题
            dataset_context (str, optional): 数据集上下文信息，包括现有的分析维度
            
        返回:
            dict: 解析后的分析大纲JSON对象
        """
        from app.ai.ai_prompt import AiPrompt
        
        # 设置用户需求
        user_requirements = '数据分析大纲'
        if isinstance(title, str) and title.strip():
            user_requirements = title
            
        # 构建分析大纲提示词
        prompt = AiPrompt.build_analysis_outline_prompt(data_summary, user_requirements, dataset_context)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            temperature=0.2,  # 降低温度以获得更确定性的输出
            prompt_type='analysis_outline'
        )
        
        # 获取分析大纲内容
        return self._parse_response(completion)

    def generate_interpretation_report(self, data_structure, jsondata, dimension_info):
        """
            数据解读生成分析报告
        """
        prompt = AiPrompt.build_data_interpretation_prompt(data_structure, jsondata, dimension_info)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='interpretation_report'
        )

        tempcontent = completion.choices[0].message.content
        tempcontent = re.sub(r'```markdown\s*', '', tempcontent)
        tempcontent = re.sub(r'```\s*$', '', tempcontent)
        
        return tempcontent
        
    def generate_report_to_html(self, report_md: str, user_requirements: str = "", additional_context: str = ""):
        """
            将Markdown格式的分析报告转换为精美HTML页面
        """
        prompt = AiPrompt.build_report_to_html_prompt(report_md, user_requirements, additional_context)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='report_to_html'
        )
        
        return completion.choices[0].message.content
        
    def generate_html_template(self, user_requirements: str = "", additional_context: str = ""):
        """
        生成HTML报告模板，用于后续填充Markdown内容
        
        参数:
            user_requirements (str, optional): 用户对报告生成的特定要求
            additional_context (str, optional): 额外的上下文信息
            
        返回:
            str: HTML模板代码
        """
        prompt = AiPrompt.build_html_template_prompt(user_requirements, additional_context)
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='html_template'
        )
        
        html_template = completion.choices[0].message.content
        
        # 清理模板代码，移除可能的```html和```标记
        html_template = re.sub(r'```html\s*', '', html_template)
        html_template = re.sub(r'```\s*$', '', html_template)
        
        return html_template

    def generate_dimension_charts(self, dimensions_data: list, tablename: str, columns: list, session_id: str, db_session=None):
        """
        为分析维度数据中的每个SQL生成Echarts配置并更新到数据库
        
        参数:
            dimensions_data (list): 分析维度数据数组，包含SQL及图表建议
            tablename (str): 数据表名
            columns (list): 数据表列名列表
            session_id (str): 会话ID，用于更新正确的分析维度记录
            db_session: 数据库会话对象，如果为None则创建新会话
            
        返回:
            bool: 处理是否成功
        """
        from sqlalchemy import create_engine
        from sqlalchemy.orm import sessionmaker
        from app.models.db import AnalysisDimension, DATABASETB_URL
        
        # 如果未提供数据库会话，则创建一个
        should_close_session = False
        if db_session is None:
            engine = create_engine(DATABASETB_URL)
            Session = sessionmaker(bind=engine)
            db_session = Session()
            should_close_session = True
            
        try:
            # 遍历分析维度数据
            for dimension in dimensions_data:
                dimension_name = dimension.get('分析维度', '')
                
                # 获取该维度的分析详情
                analysis_details = dimension.get('分析详情', [])
                
                # 为每个SQL生成Echarts配置
                chart_suggestions = []
                echarts_configs = []  # 存储所有生成的Echarts配置
                
                for detail in analysis_details:
                    sql = detail.get('sql', '')
                    chart_type = detail.get('建议图表类型', '')
                    chart_name = detail.get('建议图表名称', '')
                    
                    # 如果SQL和图表类型存在，则生成Echarts配置
                    if sql and chart_type:
                        # 用户需求可以从分析目标中提取
                        user_request = dimension.get('分析目标', '')
                        
                        # 生成Echarts配置
                        echarts_config = self.generate_echarts_config(
                            sql=sql,
                            chart_type=chart_type,
                            user_request=user_request
                        )
                        
                        # 将图表配置添加到建议列表
                        chart_suggestion = {
                            'chart_name': chart_name,
                            'chart_type': chart_type,
                            'sql': sql,
                            'echarts_config': echarts_config
                        }
                        chart_suggestions.append(chart_suggestion)
                        
                        # 添加到Echarts配置列表
                        echarts_configs.append({
                            'name': chart_name,
                            'type': chart_type,
                            'config': echarts_config
                        })
                
                # 查找对应的分析维度记录并更新
                dimension_records = db_session.query(AnalysisDimension).filter(
                    AnalysisDimension.session_id == session_id,
                    AnalysisDimension.dimension_name == dimension_name
                ).all()
                
                if dimension_records:
                    # 更新已存在的记录
                    for record in dimension_records:
                        # 更新chart_suggestions字段(向后兼容)
                        record.chart_suggestions = json.dumps(chart_suggestions, ensure_ascii=False)
                        # 更新新的recommended_charts字段
                        record.recommended_charts = json.dumps(echarts_configs, ensure_ascii=False)
                else:
                    # 找不到记录，说明数据库中尚未创建该维度
                    logger.warning(f"未找到维度记录: {dimension_name}，跳过Echarts配置更新")
            
            # 提交数据库事务
            db_session.commit()
            logger.info(f"成功为{len(dimensions_data)}个分析维度生成并更新了Echarts配置")
            return True
            
        except Exception as e:
            # 记录错误并回滚事务
            logger.error(f"生成Echarts配置时发生错误: {str(e)}")
            db_session.rollback()
            return False
            
        finally:
            # 如果是我们创建的会话，则关闭它
            if should_close_session and db_session:
                db_session.close()
                
    def fill_html_template(self, html_template: str, report_data: dict) -> str:
        """
        将报告数据填充到HTML模板中
        
        参数:
            html_template (str): HTML模板代码
            report_data (dict): 报告数据，包含以下字段:
                - title: 报告标题
                - description: 报告描述
                - content: Markdown格式的报告内容
                - toc: 目录内容 (可选)
                - created_at: 创建时间 (可选)
                
        返回:
            str: 填充好内容的HTML代码
        """
        try:
            from bs4 import BeautifulSoup
            import markdown
            import re
            import json
            
            # 解析HTML模板
            soup = BeautifulSoup(html_template, 'html.parser')
            
            # 填充报告标题
            title_element = soup.find(id='report-title')
            if title_element and 'title' in report_data:
                title_element.string = report_data['title']
                
                # 同时更新<title>标签
                title_tag = soup.find('title')
                if title_tag:
                    title_tag.string = report_data['title']
            
            # 填充报告描述
            desc_element = soup.find(id='report-description')
            if desc_element and 'description' in report_data:
                desc_element.string = report_data['description']
            
            # 填充创建时间
            time_element = soup.find(id='report-time')
            if time_element and 'created_at' in report_data:
                time_element.string = report_data['created_at']
            
            # 填充目录
            toc_element = soup.find(id='table-of-contents')
            if toc_element and 'toc' in report_data:
                toc_element.clear()
                toc_element.append(BeautifulSoup(report_data['toc'], 'html.parser'))
            
            # 填充正文内容 - 将Markdown转换为HTML
            content_element = soup.find(id='report-content')
            if content_element and 'content' in report_data:
                # 使用Python-Markdown库转换Markdown到HTML
                html_content = markdown.markdown(
                    report_data['content'],
                    extensions=['tables', 'fenced_code', 'codehilite']
                )
                content_element.clear()
                content_element.append(BeautifulSoup(html_content, 'html.parser'))
            
            # 处理表格数据，准备图表渲染
            # 查找所有表格，添加图表渲染功能
            tables = soup.find_all('table')
            for i, table in enumerate(tables):
                # 为每个表格添加一个图表容器
                canvas_id = f'chart-{i}'
                chart_container = soup.new_tag('div', **{'class': 'chart-container'})
                canvas = soup.new_tag('canvas', id=canvas_id)
                chart_container.append(canvas)
                
                # 将表格数据提取为JSON格式，以便JavaScript处理
                headers = []
                data = []
                
                # 提取表头
                thead = table.find('thead')
                if thead:
                    header_row = thead.find('tr')
                    if header_row:
                        headers = [th.get_text().strip() for th in header_row.find_all('th')]
                
                # 提取数据行
                tbody = table.find('tbody')
                if tbody:
                    for row in tbody.find_all('tr'):
                        row_data = [td.get_text().strip() for td in row.find_all('td')]
                        data.append(row_data)
                
                # 创建表格数据的JSON表示
                table_data = {
                    'headers': headers,
                    'data': data
                }
                
                # 添加数据属性到canvas元素
                canvas['data-table'] = json.dumps(table_data)
                
                # 将图表容器添加到表格之后
                table.insert_after(chart_container)
                
                # 为表格添加一个切换按钮，可以在表格和图表之间切换
                toggle_btn = soup.new_tag('button', **{
                    'class': 'toggle-view-btn',
                    'data-target': canvas_id,
                    'onclick': f'toggleView("{canvas_id}")'
                })
                toggle_btn.string = '切换图表/表格视图'
                table.insert_before(toggle_btn)
            
            # 返回完整的HTML
            return str(soup)
            
        except Exception as e:
            logger.error(f"填充HTML模板失败: {str(e)}")
            # 如果处理失败，返回原始模板和错误信息
            return f"""
            <html>
            <head><title>处理错误</title></head>
            <body>
                <h1>填充HTML模板时发生错误</h1>
                <p>错误信息: {str(e)}</p>
                <h2>原始报告内容:</h2>
                <pre>{json.dumps(report_data, ensure_ascii=False, indent=2)}</pre>
            </body>
            </html>
            """


    def generate_task_breakdown(self, user_requirement, available_datasets, conversation_context=None):
        """
        拆解任务，支持上下文感知
        
        参数:
            user_requirement: 用户需求文本
            available_datasets: 可用数据集信息
            conversation_context: 会话上下文信息（可选）
        """
        # 使用优化后的任务拆解提示词，支持上下文感知
        prompt = AiPromptTask.build_task_breakdown_prompt_strict(
            user_input=user_requirement, 
            available_datasets=json.dumps(available_datasets, ensure_ascii=False),
            conversation_context=conversation_context
        )
        
        # 使用公共方法_chat_completion替代原始代码
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='Task_Context_Aware'  # 更新提示词类型标识
        )

        return self._parse_response(completion)

    def generate_sql_from_task_prompt(self, task_info: dict, dataset_schema: dict) :
        """
        根据任务信息和数据集结构生成SQL语句
        
        参数:
            task_info (dict): 任务信息，包含任务标题和任务要求
            dataset_schema (dict): 数据集结构信息
            
        返回:
            dict: 包含SQL语句和相关信息的字典
        """
            # 使用 AiPromptTask 生成 SQL 提示词
        sql_prompt = AiPromptTask.build_task_sql_prompt(task_info, dataset_schema)
        
        # 使用公共方法_chat_completion调用AI模型
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=sql_prompt,
            prompt_type='task_sql_generation'
        )
        
        return self._parse_response(completion)
           
    def generate_intent_analysis(self, user_input: str, context: dict, available_tasks: list):
        """
        使用AI进行高级意图识别分析，支持多意图并发识别
        
        参数:
            user_input (str): 用户输入内容
            context (dict): 会话上下文信息
            available_tasks (list): 可用任务配置列表
            
        返回:
            list: 意图识别结果列表，支持多个意图
        """
                  
            # 构建高级意图识别提示词
        prompt = AiPromptTask.build_intent_analysis_prompt(user_input, context, available_tasks)
        
        # 使用公共方法_chat_completion调用AI模型
        completion = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            prompt_type='intent_recognition'
        )
        return self._parse_response(completion)

            # 解析响应
           
    
    def _get_default_unknown_intent(self, error_message: str = "无法识别用户意图"):
        """
        获取默认的未知意图响应
        
        参数:
            error_message (str): 错误信息
            
        返回:
            list: 包含单个未知意图的列表
        """
        return [{
            "intent_id": "unknown_intent_1",
            "intent_type": "unknown",
            "confidence": 0.0,
            "analysis_reason": error_message,
            "next_action": "clarify",
            "user_message": "抱歉，我没有完全理解您的需求。我可以帮您：\n\n📋 **功能调用**\n📊 **数据查询分析**\n📈 **图表生成**\n📄 **报告生成**\n📚 **知识库查询**\n\n请详细描述您想要执行的操作，我会尽力帮助您。",
        }]

    def analyze_data_with_ai(self, message: str, data: dict, conversation_context: dict):
        """
        使用AI对数据进行分析解读
        
        参数:
            taskinfo (str): 任务名称 + 任务要求
            data (list): 查询得到的数据
            
        返回:
            str: AI分析结果
        """

         # 使用新的智能提示词方法，自动判断用户意图
        prompt = AiPromptTask.build_assistant_response_prompt(message, data, conversation_context)
        prompt_type = "smart_response"
            
        # 使用公共方法_chat_completion替代原始代码，流式输出
        # 流式输出的日志记录已在_chat_completion方法中处理
        response_generator = self._chat_completion(
            model=AI_FXMODEL,
            prompt=prompt,
            stream=True,
            role="system",
            temperature=0,
            top_p=0.1,
            prompt_type=prompt_type
        )
        
        # 直接返回流式响应（此时已包含日志记录逻辑）
        for chunk in response_generator:
            content = chunk.choices[0].delta.content
            if content:
                yield content
           